package me.ak.event;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class EventManager {

	private static List<ListenerWrapper> listeners = new ArrayList<ListenerWrapper>();

	public static void addListener(Object ev) {
		validate(ev);
	}

	private static boolean validate(Object ev) {
		for (ListenerWrapper lw : listeners) {
			Object e = lw.ev;
			if (e.getClass().getName().equals(ev.getClass().getName())) {
				return false;
			}
		}

		Method[] ms = ev.getClass().getMethods();
		if (ms == null)
			return false;
		List<Method> methods = new ArrayList<Method>();
		for (Method m : ms) {
			Annotation[] as = m.getAnnotations();
			if (as == null)
				return false;
			for (Annotation a : as) {
				if (a.annotationType().getName()
						.equals(EventSubscribe.class.getName()))
					methods.add(m);
			}
		}

		if (methods.size() < 1)
			return false;

		listeners.add(new ListenerWrapper(ev, methods));
		return true;
	}
	
	
	public static void trigEvent(Object e) {
		for (ListenerWrapper lw : listeners) {
			if (lw.listeningForEvent(e)) {
				lw.callEvent(e);
			}
		}
	}
	
	
	
	

	private static class ListenerWrapper {
		public Object ev;
		public List<Method> mList = new ArrayList<Method>();

		public ListenerWrapper(Object e, List<Method> m) {
			ev = e;
			mList = m;
		}

		public boolean listeningForEvent(Object e) {
			for (Method m : mList) {
				Class<?>[] pars = m.getParameterTypes();
				if (pars != null
						&& pars[0].getName().equals(e.getClass().getName())
						&& pars.length == 1) {
					return true;
				}
			}
			return false;
		}

		public void callEvent(Object e) {
			try {
				for (Method m : mList) {
					Class<?>[] pars = m.getParameterTypes();
					if (pars != null
							&& pars[0].getName().equals(e.getClass().getName())
							&& pars.length == 1) {
						m.setAccessible(true);
						m.invoke(ev.getClass(), new Object[] { e });
					}
				}
			} catch (Exception ee) {
			}
		}
	}

}
